package me.keiwu.admin.service.impl;

import me.keiwu.admin.domain.system.SysInviteCode;
import me.keiwu.admin.domain.system.SysRole;
import me.keiwu.admin.domain.system.SysUser;
import me.keiwu.admin.dao.SysInviteCodeRepository;
import me.keiwu.admin.dao.SysRoleRepository;
import me.keiwu.admin.dao.SysUserRepository;
import me.keiwu.admin.service.UserService;
import me.keiwu.admin.util.EntityUtil;
import me.keiwu.admin.util.SecurityUtil;
import me.keiwu.admin.util.bean.RoleConst;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;


/**
 * Created by kei on 07/08/2017.
 */
@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private SysRoleRepository sysRoleRepository;
    @Autowired
    private SysUserRepository sysUserRepository;
    @Autowired
    private SysInviteCodeRepository sysInviteCodeRepository;


    @Override
    public SysUser login(String username, String password) {
        return null;
    }

    @Override
    public SysInviteCode verifyInviteCode(String code) {
        Optional<SysInviteCode> res = sysInviteCodeRepository.findByCode(code);
        if (!res.isPresent()) return null;
        SysInviteCode c = res.get();
        if (!c.isValid()) return null;
        c.setValid(false);
        sysInviteCodeRepository.save(c);
        return c;
    }

    @Override
    public void addInviteCodes(List<String> codes, int type) {
        List<SysInviteCode> codeList = new ArrayList<>();
        codes.forEach(c -> {
            SysInviteCode code = new SysInviteCode();
            code.setValid(true);
            code.setCode(c);
            code.setType(type);
            EntityUtil.setModifiedBy(code, true);
            codeList.add(code);
        });
        sysInviteCodeRepository.save(codeList);
    }

    @Override
    public UserDetails loadUserByUsername(@NotNull String s) throws UsernameNotFoundException {
        SysUser res = sysUserRepository.findOneWithRolesByUsername(s);
        if (res == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        return res;
    }

    @Override
    public SysUser register(@NotNull String username, @NotNull String password, @NotNull Integer type,
                            String firstName, String lastName, String email, String imageUrl) {
        SysUser user = new SysUser();
        user.setUsername(username);
        if (!EntityUtil.setModifiedBy(user, true)) return null;
        // BCrypt
        user.setPassword(SecurityUtil.encryptPassword(password));
        user.setFirstName(firstName);
        user.setLastName(lastName);
        user.setEmail(email);
        user.setImageUrl(imageUrl);
        user.setEnable(true);

        Set<SysRole> sysRoles = new HashSet<>();
        RoleConst roleConst = RoleConst.parse(type);
        if (roleConst != null) {
            SysRole role = sysRoleRepository.findByValue(roleConst.getValue());
            sysRoles.add(role);
            user.setRoles(sysRoles);
            sysUserRepository.save(user);
            return user;
        }
        return null;
    }


    @Override
    public boolean changeProfile(SysUser user, String firstName, String lastName, String email, String imageUrl) {
        if (!EntityUtil.setModifiedBy(user)) return false;
        user.setFirstName(firstName);
        user.setLastName(lastName);
        user.setEmail(email);
        user.setImageUrl(imageUrl);
        sysUserRepository.save(user);
        return true;
    }

    @Override
    public boolean changePassword(SysUser user, String password) {
        if (!EntityUtil.setModifiedBy(user)) return false;
        user.setPassword(SecurityUtil.encryptPassword(password));
        sysUserRepository.save(user);
        return true;
    }

    @Override
    public boolean changeRoles(SysUser user, Set<SysRole> roleSet) {
        if (!EntityUtil.setModifiedBy(user)) return false;
        user.setRoles(roleSet);
        sysUserRepository.save(user);
        return true;
    }
}
